package com.steakliu.sun.boot.starter;

import com.steakliu.sun.boot.starter.helper.ConfigInfoHelper;
import com.steakliu.sun.boot.starter.helper.PropertiesHelper;
import com.steakliu.sun.boot.starter.prop.ConfigCenterProperties;
import com.steakliu.sun.boot.starter.prop.Prop;
import com.steakliu.sun.boot.starter.prop.SunClientProperties;
import com.steakliu.sun.client.api.ClientConfig;
import com.steakliu.sun.client.spring.SunFactoryBean;
import com.steakliu.sun.spi.loader.ExtensionLoader;
import lombok.SneakyThrows;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

/**
 * 功能说明： 如果注解上没有设置值，则使用yml文件中的值进行填充，yml中也没有设置，使用默认值
 * <p>
 * Original @Author: steakliu-刘牌, 2023-0105  17:04
 * <p>
 * Copyright (C)2020-2022  steakliu All rights reserved.
 */
@Component
public class PropPopulatePostProcessor implements BeanPostProcessor, ApplicationContextAware {

    private PropertiesHelper propertiesHelper;

    @Autowired
    private ConfigCenterProperties configCenterProperties;

    private SunClientProperties clientProperties;

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof SunFactoryBean) {
            SunFactoryBean factoryBean = (SunFactoryBean) bean;
            return this.populate(factoryBean);
        }
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    private SunFactoryBean populate(SunFactoryBean factoryBean) {
        ClientConfig clientConfig = factoryBean.getClientConfig();
        try {
            clientConfig = ClientConfig.builder()
                    .version(clientConfig.getVersion().isEmpty() ? clientProperties.getVersion() : clientConfig.getVersion())
                    .group(clientConfig.getGroup().isEmpty() ? clientProperties.getGroup() : clientConfig.getGroup())
                    .registryType(clientConfig.getRegistryType().isEmpty() ? clientProperties.getRegistryType() : clientConfig.getRegistryType())
                    .registryAddress(clientConfig.getRegistryAddress().isEmpty() ? clientProperties.getRegistryAddress() : clientConfig.getRegistryAddress())
                    .serializer(clientConfig.getSerializer().isEmpty() ? clientProperties.getSerializer() : clientConfig.getSerializer())
                    .proxy(clientConfig.getProxy().isEmpty() ? clientProperties.getProxy() : clientConfig.getProxy())
                    .timeout(clientConfig.getTimeout() == 0 ? clientProperties.getTimeout() == 0 ? 0 : clientProperties.getTimeout() : clientConfig.getTimeout())
                    .async(!clientConfig.isAsync() ? clientProperties.isAsync() : clientConfig.isAsync())
                    .oneway(!clientConfig.isOneway() ? clientProperties.isOneway() : clientConfig.isOneway())
                    .loadBalance(clientConfig.getLoadBalance().isEmpty() ? clientProperties.getLoadBalance() : clientConfig.getLoadBalance())
                    .cache(!clientConfig.isCache() ? clientProperties.isCache() : clientConfig.isCache())
                    .cacheTime(clientConfig.getCacheTime() == 0 ? clientProperties.getCacheTime() == 0 ? 0 : clientProperties.getCacheTime() : clientConfig.getCacheTime())
                    .heartbeatInterval(clientConfig.getHeartbeatInterval() == 0 ? clientProperties.getHeartbeatInterval() == 0 ? 0 : clientProperties.getRetryInterval() : clientConfig.getHeartbeatInterval())
                    .heartbeatRetries(clientConfig.getHeartbeatRetries() == 0 ? clientProperties.getHeartbeatRetries() == 0 ? 0 : clientProperties.getHeartbeatRetries() : clientConfig.getHeartbeatRetries())
                    .retries(clientConfig.getRetries() == 0 ?clientProperties.getRetries() == 0 ? 0 : clientProperties.getRetries() : clientConfig.getRetries())
                    .retryInterval(clientConfig.getRetryInterval() == 0 ? clientProperties.getRetryInterval() == 0 ? 0 : clientProperties.getRetryInterval() : clientConfig.getRetryInterval())
                    .token(clientConfig.getToken().isEmpty() ? clientProperties.getToken() : clientConfig.getToken())
                    .directConnections(clientConfig.getDirectConnections().isEmpty() ? clientProperties.getDirectConnections() : clientConfig.getDirectConnections())
                    .flowControlType(clientConfig.getFlowControlType().isEmpty() ? clientProperties.getFlowControlType() : clientConfig.getFlowControlType())
                    .useFlowControl(clientConfig.isUseFlowControl() ? clientProperties.isUseFlowControl() : clientConfig.isUseFlowControl())
                    .concurrentCorePoolSize(clientProperties.getConcurrentCorePoolSize())
                    .concurrentMaximumPoolSize(clientConfig.getConcurrentMaximumPoolSize())
                    .reflectType(clientConfig.getReflectType())
                    .useRateLimit(clientProperties.isUseRateLimit())
                    .rateLimiterType(clientProperties.getRateLimiterType())
                    .milliseconds(clientProperties.getMilliseconds())
                    .permits(clientProperties.getPermits())
                    .rateLimiterFailStrategy(clientProperties.getRateLimiterFailStrategy())
                    .enableBuffer(clientProperties.isEnableBuffer())
                    .bufferType(clientProperties.getBufferType())
                    .build();
            factoryBean.setClientConfig(clientConfig);
        }catch (Exception e){
            e.printStackTrace();
        }
        return factoryBean;
    }

    @SneakyThrows
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        Prop prop = ConfigInfoHelper.getProp(configCenterProperties);
        this.clientProperties = prop.getSun().getClient();
    }
}
